package org.karelun.whiteboard.ui.local.editor;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.EMFEditPlugin;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.karelun.whiteboard.Triangle;
import org.karelun.whiteboard.edit.factory.PartFactory;
import org.karelun.whiteboard.edit.factory.WhiteboardCreationFactory;
import org.karelun.whiteboard.gef.DefaultEditDomain;
import org.karelun.whiteboard.gef.editparts.ScalableFreeformRootEditPart;
import org.karelun.whiteboard.gef.palette.CreationToolEntry;
import org.karelun.whiteboard.gef.palette.MarqueeToolEntry;
import org.karelun.whiteboard.gef.palette.PaletteDrawer;
import org.karelun.whiteboard.gef.palette.PaletteGroup;
import org.karelun.whiteboard.gef.palette.PaletteRoot;
import org.karelun.whiteboard.gef.palette.SelectionToolEntry;
import org.karelun.whiteboard.gef.palette.ToolEntry;
import org.karelun.whiteboard.gef.ui.parts.GraphicalEditorWithFlyoutPalette;

/**
 * @Author: KarelunHuang
 * @Date: Jan 23, 2013
 **/
public class LocalEditor extends GraphicalEditorWithFlyoutPalette {

	private ComposedAdapterFactory adapterFactory;
	
	private AdapterFactoryEditingDomain editingDomain;
	
	public LocalEditor() {
		ComposedAdapterFactory.Descriptor.Registry registry = EMFEditPlugin.getComposedAdapterFactoryDescriptorRegistry();
		adapterFactory = new ComposedAdapterFactory(registry);
		adapterFactory.addAdapterFactory(new ResourceItemProviderAdapterFactory());
		adapterFactory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory());
		editingDomain=new AdapterFactoryEditingDomain(adapterFactory, new BasicCommandStack(),new HashMap<Resource, Boolean>());
		setEditDomain(new DefaultEditDomain(this,editingDomain));
	}
	
	@Override
	public void init(IEditorSite site, IEditorInput input)
			throws PartInitException {
		super.init(site, input);
		URI resourceURI=(URI)input.getAdapter(URI.class);
		editingDomain.getResourceSet().getResource(resourceURI, true);
	}
	
	@Override
	protected void configureGraphicalViewer() {
		super.configureGraphicalViewer();
		ScalableFreeformRootEditPart rootEditPart = new ScalableFreeformRootEditPart();
		getGraphicalViewer().setRootEditPart(rootEditPart);
		getGraphicalViewer().setEditPartFactory(new PartFactory());
	}
	
	@Override
	protected void initializeGraphicalViewer() {
		EObject content = editingDomain.getResourceSet().getResources().get(0).getContents().get(0);
		getGraphicalViewer().setContents(content);
	}

	@Override
	protected PaletteRoot getPaletteRoot() {
		PaletteRoot root = new PaletteRoot();
		PaletteGroup toolGroup = new PaletteGroup("Whiteboard");

		ToolEntry selectTool = new SelectionToolEntry();
		ToolEntry marqueTool = new MarqueeToolEntry();
		toolGroup.add(selectTool);
		toolGroup.add(marqueTool);

		root.setDefaultEntry(selectTool);
		root.add(toolGroup);

		PaletteDrawer drawer = new PaletteDrawer("Triangle");
		CreationToolEntry shapeEntry = new CreationToolEntry("Triangle", "",
				new WhiteboardCreationFactory(Triangle.class), null, null);
		drawer.add(shapeEntry);
		root.add(drawer);
		return root;
	}

	@Override
	public void doSave(IProgressMonitor monitor) {
		final Map<Object, Object> saveOptions = new HashMap<Object, Object>();
		saveOptions.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED, Resource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER);
		IRunnableWithProgress saveOperation = new IRunnableWithProgress(){
			public void run(IProgressMonitor monitor)
					throws InvocationTargetException, InterruptedException {
				for(Resource resource:editingDomain.getResourceSet().getResources()){
					try {
						resource.save(saveOptions);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		};
		try {
			new ProgressMonitorDialog(getSite().getShell()).run(true, false, saveOperation);
			((BasicCommandStack) editingDomain.getCommandStack()).saveIsDone();
			firePropertyChange(IEditorPart.PROP_DIRTY);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean isDirty() {
		BasicCommandStack commandStack=(BasicCommandStack)editingDomain.getCommandStack();
		return commandStack.isSaveNeeded();
	}
}
